package com.atguigu.dga.assess.assess.quality;

import com.alibaba.fastjson.JSON;
import com.atguigu.dga.assess.assess.AssessorTemplate;
import com.atguigu.dga.assess.bean.AssessParam;
import com.atguigu.dga.assess.bean.GovernanceAssessDetail;
import com.atguigu.dga.assess.bean.GovernanceMetric;
import com.atguigu.dga.config.MetaConstant;
import com.atguigu.dga.ds.bean.TDsTaskInstance;
import com.atguigu.dga.ds.service.TDsTaskInstanceService;
import com.atguigu.dga.meta.bean.TableMetaInfo;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import jdk.nashorn.internal.scripts.JS;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;

/*
前一天（数据的）产出时效，超过前{days}天产出时效平均值n%则给0分，其余10分
    ①计算Task当天运行的时间(endtime - starttime)
    ②计算Task前days天的平均运行时间 avg(endtime - starttime)
    ③计算比例
 */
@Component("TABLE_PRODUCE_EFFICIENCY")
public class TableProduceTimeEfficient extends AssessorTemplate {
    @Autowired
    private TDsTaskInstanceService instanceService;

    /*
    ods层表是直接通过脚本load的
           都不会生成Task
           也就不会有什么时效信息！排除ODS层！
     */
    @Override
    protected void assess(AssessParam param, GovernanceAssessDetail detail) throws Exception {
        //获取当前表的名字
        TableMetaInfo tableMetaInfo = param.getTableMetaInfo();
        String dwLevel = tableMetaInfo.getTableMetaInfoExtra().getDwLevel();
        //排除ods层及不需要Task调度表
        if (MetaConstant.DW_LEVEL_ODS.equals(dwLevel) || tableMetaInfo.getTableName().contains("dim_date")){
            return;
        }
        //获取相关参数
        GovernanceMetric metric = param.getMetric();
        Integer days = JSON.parseObject(metric.getMetricParamsJson()).getInteger("days");
        Integer n = JSON.parseObject(metric.getMetricParamsJson()).getInteger("n");
        String assessDate = param.getAssessDate();

        //获取当前表的名字

        String name = tableMetaInfo.getSchemaName() + "." + tableMetaInfo.getTableName();

        //①计算Task当天运行的时间(endtime - starttime)
        QueryWrapper<TDsTaskInstance> queryWrapper = new QueryWrapper<TDsTaskInstance>()
                .eq("name", name)
                .eq("date(start_time)", assessDate)
                .eq("state", MetaConstant.TASK_STATE_SUCCESS)
                .select("TIMESTAMPDIFF(SECOND ,start_time,end_time) sec");

        /*
        当前查询的结果是一行一列的，封装为Bean，必须要求这一列的列名在Bean中有对应属性名的
        getMap():会把查询的列，按照列名作为key,列值作为value,封装到一个Map集合中
                用于单行查询
            举例：查询完是两列 a = 1 ,b = 2
            封装的结果：{a=1,b=2}
         */
        Long sec = (Long) instanceService.getMap(queryWrapper).get("sec");


        /*
        ②计算Task前days天的平均运行时间 avg(endtime - starttime)
        ...
        where date(start_time) > date_sub(assess_date,days) and date(start_time) < assess_date
         */
        //①计算Task当天运行的时间(endtime - starttime)
        QueryWrapper<TDsTaskInstance> queryWrapper2 = new QueryWrapper<TDsTaskInstance>()
                .eq("ifnull(avg(TIMESTAMPDIFF(SECOND ,start_time,end_time)),0.0) avgSec", name)
                .eq("name", name)
                .eq("state", MetaConstant.TASK_STATE_SUCCESS)
                .last("and date(start_time) >= DATE_SUB( '" + assessDate + " ',INTERVAL " + days + "DAY ) and date(start_time) < ' " + assessDate + "'");

        BigDecimal avgSec = (BigDecimal) instanceService.getMap(queryWrapper2).get("avgSec");


        //如果当前是第一天调度，直接退出
        if (avgSec.compareTo(BigDecimal.ZERO) == 0){
            return;
        }

        //运算比较
        //极限值
        BigDecimal upperTime = avgSec.multiply(BigDecimal.valueOf(100).add(BigDecimal.valueOf(n))).movePointLeft(2);
        //今天运行的时效低
        if (BigDecimal.valueOf(sec).compareTo(upperTime) == 1){
            assessZeroScore(detail,"当前运行时间:" + sec + "秒，超过了过去" + days + " 天的平均值 " + avgSec +" 的" + n + "%" ,param,false);
        }
    }
}
